/*
 * structs.c
 *
 *  Created on: Jun 25, 2011
 *      Author: tualibano
 */

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>

#include "configurar.h"
#include "structs.h"
#include "menu.h"

int ComparaVizinho(Vizinho *v1, Vizinho *v2) {
	int diferente = 0;
	if (strcmp(v1->Ip, v2->Ip)) {
		diferente = 1;
	} else if (v1->PortaTcp != v2->PortaTcp)
		diferente = 1;
	return diferente;
}

void ZerarVizinho(Vizinho *elemento) {
	elemento->Latencia = 0;
	elemento->PortaTcp = 0;
	elemento->PortaUdp = 0;
	strcpy((elemento->Ip), "0.0.0.0");
	return;
}

void CriarTabelaVizinho(TabelaVizinhos **Tabela) {
	TabelaVizinhos *novaTabela;
	int i;
	novaTabela = (TabelaVizinhos *) malloc(sizeof(TabelaVizinhos));
	novaTabela->BlocoAnterior = NULL;
	novaTabela->ProximoBloco = NULL;
	novaTabela->vagas = CAPACIDADE_TABELA;
	for (i = 0; i < CAPACIDADE_TABELA; i++)
		ZerarVizinho(&(novaTabela->Vizinhos[i]));
	(*Tabela) = novaTabela;
	return;
}

int AdicionarVizinho(TabelaVizinhos *Tabela, Vizinho *Novo) {
	TabelaVizinhos *bTabela = Tabela;
	Vizinho v0;

	vizinhos++;

	ZerarVizinho(&v0);
	if (!ComparaVizinho(&v0, Novo))
		return 0;
	if (BuscaTabela(bTabela, Novo))
		return 0;
	int novolugar;
	if ((bTabela->vagas == 0) && (bTabela->ProximoBloco != NULL)) {
		bTabela = bTabela->ProximoBloco;
		AdicionarVizinho(bTabela, Novo);
		return 1;
	} else if ((Tabela->vagas == 0)) {
		CriarTabelaVizinho(&(bTabela->ProximoBloco));
		bTabela->ProximoBloco->BlocoAnterior = bTabela;
		AdicionarVizinho(bTabela, Novo);
		return 1;
	} else {
		novolugar = CAPACIDADE_TABELA - bTabela->vagas;
		strcpy(bTabela->Vizinhos[novolugar].Ip, Novo->Ip);
		bTabela->Vizinhos[novolugar].Latencia = Novo->Latencia;
		bTabela->Vizinhos[novolugar].PortaTcp = Novo->PortaTcp;
		bTabela->Vizinhos[novolugar].PortaUdp = Novo->PortaUdp;
		bTabela->vagas--;
	}
	return 1;
}

int RemoverVizinho(TabelaVizinhos *Tabela, Vizinho *eliminar) {
	TabelaVizinhos *bTabela = Tabela;
	int deletado = 0;
	int cont = 0;
	int transferir;
	while (cont < CAPACIDADE_TABELA) {
		if (!ComparaVizinho(&(bTabela->Vizinhos[cont]), eliminar)) {
			if (bTabela->vagas != (CAPACIDADE_TABELA - 1)) {
				transferir = CAPACIDADE_TABELA - bTabela->vagas;
				transferir--;
				strcpy(bTabela->Vizinhos[cont].Ip,
						bTabela->Vizinhos[transferir].Ip);
				bTabela->Vizinhos[cont].PortaUdp
						= bTabela->Vizinhos[transferir].PortaUdp;
				bTabela->Vizinhos[cont].PortaTcp
						= bTabela->Vizinhos[transferir].PortaTcp;
				ZerarVizinho(&(bTabela->Vizinhos[transferir]));
			} else {
				ZerarVizinho(&(bTabela->Vizinhos[cont]));
			}
			bTabela->vagas++;
			return 1;
		}
		cont++;
	}
	if (bTabela->ProximoBloco != NULL) {
		deletado = RemoverVizinho(bTabela->ProximoBloco, eliminar);
	}
	return deletado;
}

Vizinho * BuscaTabela(TabelaVizinhos *btabela, Vizinho *elemento) {

	int cont = 0;
	Vizinho v0;
	TabelaVizinhos *tabela = btabela;

	ZerarVizinho(&v0);

	while (tabela != NULL) {
		while (cont < CAPACIDADE_TABELA) {
			if (!ComparaVizinho(&tabela->Vizinhos[cont], &v0))
				break;
			else if (!ComparaVizinho(&tabela->Vizinhos[cont], elemento)) {
				return &tabela->Vizinhos[cont];
			}
			cont++;
		}
		cont = 0;
		tabela = tabela->ProximoBloco;
	}
	return NULL;
}

int PrintTabela(TabelaVizinhos *tabela) {
	int cont = 0;
	Vizinho v0;

	ZerarVizinho(&v0);

	while (tabela != NULL) {
		puts("\n Tabela:");
		printf("\n Vagas na tabela atual: %d", tabela->vagas);
		while (cont < CAPACIDADE_TABELA) {
			if (!ComparaVizinho(&tabela->Vizinhos[cont], &v0))
				break;
			printf("\n ip:%s, porta tcp: %d, porta udp: %d",
					tabela->Vizinhos[cont].Ip, tabela->Vizinhos[cont].PortaTcp,
					tabela->Vizinhos[cont].PortaUdp);
			cont++;
		}
		cont = 0;
		tabela = tabela->ProximoBloco;
	}
	puts("\nFim print tabela");
	return 0;
}

int SendTabela(TabelaVizinhos *tabela, int socket) {
	int cont = 0;
	Vizinho v0;
	char buffer[200];

	ZerarVizinho(&v0);
	while (tabela != NULL) {
		while (cont < CAPACIDADE_TABELA) {
			if (!ComparaVizinho(&tabela->Vizinhos[cont], &v0))
				break;
			sprintf(buffer, ";%s:%d:%d;/", tabela->Vizinhos[cont].Ip,
					tabela->Vizinhos[cont].PortaTcp,
					tabela->Vizinhos[cont].PortaUdp);
			//printf("\nenviando: %s\n", buffer);
			send(socket, buffer, 29, 0);
			cont++;
		} //  ;127.127.127.127:99000:99000;
		cont = 0;
		tabela = tabela->ProximoBloco;
	}
	sprintf(buffer, ";%s:%d:%d;/", v0.Ip, v0.PortaTcp, v0.PortaUdp);
	send(socket, buffer, 29, 0);
	return 0;
}

int StrFiltraIp(char *str, int tamanho) {
	int cont = 0;

	while (cont < tamanho) {
		if (str[cont] == '\0') {
			str[cont] = '/';
		} else if (str[cont] < 46 || str[cont] > 59) {
			str[cont] = '/';
		}
		cont++;
	}
	str[cont] = '\0';
	return 0;
}